
package com.hlkj.pay.app.merchant.ext.impl.baofu.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.merchant.ext.impl.baofu.dto.BaoFuConfig;
import com.hlkj.pay.app.merchant.ext.impl.baofu.dto.res.BaoFuCommonRes;
import com.hlkj.pay.app.merchant.ext.impl.baofu.util.BaoFuSigner;
import com.hlkj.pay.app.merchant.ext.impl.baofu.util.BaoFuVerifier;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.LakalaConfig;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.resp.LakalaTokenRes;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.util.DateUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 汇付 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
@Service
public class BaofuMerchantCommonParamsHandle {

    private String accessToken;

    private long tokenExpires;

    @Autowired
    private OkHttpTemplate okHttpTemplate;

    @Value("${spring.profiles.active}")
    private String active;

    public CommonResult<BaoFuCommonRes> request(Map<String, Object> params, String requestId, String requestType, String callBack, BaoFuConfig baoFuConfig, boolean test) {
        try {
            TreeMap<String, String> postParam = new TreeMap<>();
            postParam.put("app_id", baoFuConfig.getAppId());
            postParam.put("sign_type", "RSA");
            postParam.put("client_trans_id", requestId);
            postParam.put("trans_timestamp", DateUtils.dateToString(System.currentTimeMillis(), "yyyyMMddHHmmss"));
            postParam.put("trans_type", requestType);
            postParam.put("callback_url", callBack);
            postParam.put("version", "1.0.0");
            String data = JsonUtils.toJsonString(params);
            log.info("宝付请求 签名前的json data:{}", data);
            // postParam.put("data", BaoFuSigner.Base64Encode(data));
            postParam.put("data", BaoFuSigner.Base64Encode(data));
            String reqSignStr = BaoFuSigner.concatTreeMapParam(postParam);
            log.info("宝付请求 待签名字符 reqSignStr:{}", reqSignStr);
            String sign = BaoFuSigner.sign(reqSignStr, baoFuConfig.getPriKeyPath(), baoFuConfig.getPriKeyPassWord());
            log.info("宝付请求 签名结果 sign:{}", sign);
            postParam.put("sign", sign);
            postParam.put("data", URLEncoder.encode(BaoFuSigner.Base64Encode(data),"UTF-8"));
            String requestData = JsonUtils.toJsonString(postParam);
            log.info("宝付请求 请求参数 requestData:{}", requestData);
            //https://rzt.mandao-tech.com/api/trade
            // String results = requestForm("https://v-rzt.mandao-tech.com/api/trade", postParam);
            String results = requestForm("https://rzt.mandao-tech.com/api/trade", postParam);
            log.info("宝付请求 响应结果 results:{}", results);
            BaoFuCommonRes baoFuCommonRes = JsonUtils.parseObject(results, BaoFuCommonRes.class);
            Boolean bool = verifyByCerFile(results,baoFuConfig);
            log.info("宝付请求 验签结果:" + bool);
            Map<String, String> mapResult = JsonUtils.parseObject(results, Map.class);// 将响应结果转化为TreeMap对象。
            String response = BaoFuSigner.Base64Decode(mapResult.get("data"));
            log.info("宝付请求 业务响应结果 response :{}", response);
            baoFuCommonRes.setData(response);
            if ("00000000".equals(baoFuCommonRes.getResp_code())) {
                return CommonResult.success(baoFuCommonRes);
            }
            else {
                return CommonResult.error(1, baoFuCommonRes.getResp_msg());
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }
    }

    public CommonResult<BaoFuCommonRes> requestFile(Map<String, File> params, String requestId, String requestType, String callBack, BaoFuConfig baoFuConfig, boolean test) {
        try {
            TreeMap<String, String> postParam = new TreeMap<>();
            postParam.put("app_id", baoFuConfig.getAppId());
            postParam.put("sign_type", "RSA");
            postParam.put("client_trans_id", requestId);
            postParam.put("trans_timestamp", DateUtils.dateToString(System.currentTimeMillis(), "yyyyMMddHHmmss"));
            postParam.put("trans_type", requestType);
            postParam.put("callback_url", callBack);
            postParam.put("version", "1.0.0");
            String data = JsonUtils.toJsonString(params);
            postParam.put("data", BaoFuSigner.Base64Encode(data));
            String reqSignStr = BaoFuSigner.concatTreeMapParam(postParam);
            log.info("宝付文件请求 待签名字符 reqSignStr:{}", reqSignStr);
            String sign = BaoFuSigner.sign(reqSignStr, baoFuConfig.getPriKeyPath(), baoFuConfig.getPriKeyPassWord());
            log.info("宝付文件请求 签名结果 sign:{}", sign);
            postParam.put("sign", sign);
            String requestData = JsonUtils.toJsonString(postParam);
            log.info("宝付文件请求 请求参数 requestData:{}", requestData);
            String results = doUploadFile("https://rzt.mandao-tech.com/api/trade", params, postParam);
            log.info("宝付文件请求 响应结果 results:{}", results);
            BaoFuCommonRes baoFuCommonRes = JsonUtils.parseObject(results, BaoFuCommonRes.class);
            Boolean bool = verifyByCerFile(results,baoFuConfig);
            log.info("宝付文件请求 验签结果:" + bool);
            Map<String, String> mapResult = JsonUtils.parseObject(results, Map.class);// 将响应结果转化为TreeMap对象。
            String response = BaoFuSigner.Base64Decode(mapResult.get("data"));
            log.info("宝付文件请求 业务响应结果 response :{}", response);
            baoFuCommonRes.setData(response);
            if ("00000000".equals(baoFuCommonRes.getResp_code())) {
                return CommonResult.success(baoFuCommonRes);
            }
            else {
                return CommonResult.error(1, baoFuCommonRes.getResp_msg());
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }
    }
   public boolean verifyByCerFile(String results,BaoFuConfig baoFuConfig){
        TreeMap<String, String> mapResult = JsonUtils.parseObject(results, TreeMap.class);// 将响应结果转化为TreeMap对象。
        String sign = mapResult.get("sign");
        mapResult.remove("sign");
        String signStr = BaoFuSigner.concatTreeMapParam(mapResult);// 生成待验签字符串
        log.info("宝付返回数据 待验签字符 signStr :{}", signStr);
        return BaoFuVerifier.verifyByCerFile(signStr, sign, baoFuConfig.getBfCerPath());
    }

    // http请求
    public String requestForm(String url, Map<String, String> params) throws Exception {
        if (params.isEmpty()) {
            return "参数不能为空！";
        }
        String postParms = "";
        for (String key : params.keySet()) {
            if (!key.isEmpty()) {
                postParms += key + "=" + params.get(key) + "&";
            }
        }
        postParms = postParms.substring(0, postParms.length() - 1);
        return okHttpTemplate.post(url + "?" + postParms, null);
    }

    public static String doUploadFile(String url, Map<String, File> files, Map<String, String> params) {
        if (StringUtils.isEmpty(url) || null == files) {
            return null;
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        try {
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));// 设置请求的编码格式
            multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);// 设置浏览器兼容模式
            if (files != null && files.size() > 0) {
                Set<Map.Entry<String, File>> entries = files.entrySet();
                for (Map.Entry<String, File> entry : entries) {
                    multipartEntityBuilder.addPart(entry.getKey(), new FileBody(entry.getValue()));
                }
            }
            ContentType contentType = ContentType.create("text/plain", "UTF-8");
            // 如果有额外的请求参数
            if (params != null && !params.isEmpty()) {
                for (String key : params.keySet()) {
                    multipartEntityBuilder.addPart(key, new StringBody(params.get(key), contentType));
                }
            }
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(multipartEntityBuilder.build());
//	            httpPost.addHeader("Content-Type", "multipart/form-data; boundary=----------ThIs_Is_tHe_bouNdaRY_$");
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                httpPost.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            return EntityUtils.toString(response.getEntity(), "UTF-8");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (null != response) {
                    response.close();
                }
                if (null != httpClient) {
                    httpClient.close();
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public CommonResult<BaoFuConfig> baoFuConfig(ProviderChannelConfigDO providerChannelConfigDO, boolean test) {
        String paramsConfig = providerChannelConfigDO.getParamsConfig();
        if (StringUtils.isEmpty(paramsConfig)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS);
        }
        // 配置转换
        BaoFuConfig baoFuConfig = null;
        try {
            baoFuConfig = JsonUtils.parseObject(paramsConfig, BaoFuConfig.class);
            if (!active.equals("prod")) {
                log.info("宝付非prod 环境,更新证书信息");
                baoFuConfig.setBfCerPath(baoFuConfig.getBfCerPath().replace("/www/wwwroot/pay/uploads/secret/20241223/", "E:/work/local_file/secret/20241223/"));
                baoFuConfig.setPriKeyPath(baoFuConfig.getPriKeyPath().replace("/www/wwwroot/pay/uploads/secret/20241223/", "E:/work/local_file/secret/20241223/"));
            }

            return CommonResult.success(baoFuConfig);
        }
        catch (Exception e) {
            String format = String.format(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getMsg(), "宝付");
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS.getCode(), format);
        }
    }

    Map<String, String> headerMap(LakalaConfig lakalaConfig, boolean test) {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Bearer " + token(lakalaConfig, test).getData());
        return headerMap;
    }

    public CommonResult<String> token(LakalaConfig lakalaConfig, boolean test) {
        long currentTimeMillis = System.currentTimeMillis();
        if (StringUtils.hasText(accessToken) && (tokenExpires - currentTimeMillis) > 1000) {
            log.info("当前token 有效:{}", accessToken);
            return CommonResult.success(accessToken);
        }
        log.info("拉卡拉 token 已失效 从新获取 tokenExpires:{},currentTimeMillis:{},time:{}", tokenExpires, currentTimeMillis, tokenExpires - currentTimeMillis);
        // .url("https://test.wsmsd.cn/sit/htkauth/oauth/token?grant_type=client_credentials&client_id=testsit&client_secret=EguwEckByf2I6u6z")
        StringBuilder sb = new StringBuilder(tokenUrl(test));
        sb.append("/oauth/token?grant_type=client_credentials&client_id=").append(lakalaConfig.getClientId());
        sb.append("&client_secret=").append(lakalaConfig.getClientSecret());
        try {
            String post = okHttpTemplate.post(sb.toString(), null);
            LakalaTokenRes lakalaTokenRes = JsonUtils.parseObject(post, LakalaTokenRes.class);
            if (StringUtils.isEmpty(lakalaTokenRes.getAccess_token())) {
                String format = String.format(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getMsg(), "拉卡拉");
                format = format + lakalaTokenRes.getError_description();
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), format);
            }
            accessToken = lakalaTokenRes.getAccess_token();
            tokenExpires = currentTimeMillis + lakalaTokenRes.getExpires_in() * 1000;
            return CommonResult.success(accessToken);
        }
        catch (Exception e) {
            log.error("获取拉卡拉token 失败:{}", e.getMessage());
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), e.getMessage());
        }
    }

    public static String date(String date) {
        if (!StringUtils.hasText(date)) {
            return null;
        }
        return date;
    }

    public static String companyType(String code) {
        // 1：政府机构
        // 2：国营企业
        // 3：私营企业
        // 4：外资企业
        // 5：个体工商户
        // 6：其它组织
        // 7：事业单位
        // 8：业主委员会；
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 2011 企业法人（国有企业）
        // 2012 企业法人（其它）
        // 2020 非法人企业
        // 2030 金融机构
        // 2040 事业单位
        // 2050 社会团体
        // 2060 党政机关
        // 2061 中央政府
        // 2062 地方政府
        // 2063 社会保障基金
        // 2064 外国政府
        // 2065 住房公积金
        // 2070 个体工商户
        // 2080 小微企业
        // 2090 代表处(驻华机构)
        // 2100 部队
        // 2110 国际组织
        // 2120 农村合作社
        // 9999 其他
        switch (code) {
            case "1":
                return "2062";
            case "2":
                return "2011";
            case "3":
                return "2080";
            case "5":
                return "2070";
            case "6":
                return "9999";
            case "7":
                return "2040";
            default:
                return null;
        }
    }

    public static String licenseType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1：营业执照
        // 2：营业执照(多证合一)
        // 3：事业单位法人证书
        // 4：社会团体法人登记证书
        // 5：民办非企业单位登记证书
        // 6：基金会法人登记证书
        // 7：宗教活动场所登记证
        // 8：其他证书/批文/证明
        // 9：执业许可证/执业证
        // 10：基层群众性自治组织特别法人统一社会信用代码证
        // 11：农村集体经济组织登记证
        // 12：业主委员会备案证明

        // 2011 企业法人（国有企业）
        // 2012 企业法人（其它）
        // 2020 非法人企业
        // 2030 金融机构
        // 2040 事业单位
        // 2050 社会团体
        // 2060 党政机关
        // 2061 中央政府
        // 2062 地方政府
        // 2063 社会保障基金
        // 2064 外国政府
        // 2065 住房公积金
        // 2070 个体工商户
        // 2080 小微企业
        // 2090 代表处(驻华机构)
        // 2100 部队
        // 2110 国际组织
        // 2120 农村合作社
        // 9999 其他
        switch (code) {
            case "1":
            case "2":
                return "2012";
            case "3":
                return "2040";
            case "4":
                return "2050";
            case "9":
                return "99";
            case "10":
                return "12";
            case "11":
                return "12";
            case "12":
                return "15";
            default:
                return null;
        }
    }

    public static String certType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1:身份证
        // 2:护照
        // 3:军官证
        // 4:士兵证
        // 5:回乡证
        // 6:户口本
        // 7:外国护照
        // 8:其他
        // 9:暂住证
        // 10:警官证
        // 11:文职干部证
        // 12:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        // 16：营业执照 （只有部分场景才会用到 如 受益人和股东）

        // 0 居民身份证或临时身份证
        // 1 军人或武警身份证件
        // 2 港澳居民来往内地通行证
        // 3 台湾居民来往大陆通行证或其他有效旅行证件
        // 4 外国公民护照
        // 5 其他类个人身份有效证件
        // 7 临时居民身份证
        // 8 港澳居民居住证
        // 9 外国人居留证
        // 10 台湾居民居住证
        // 101 统一社会信用代码
        switch (code) {
            case "1":
                return "0";
            case "2":
            case "7":
                return "4";
            case "3":
            case "4":
            case "11":
                return "1";
            case "5":
                return "3";
            case "12":
                return "9";
            case "13":
                return "4";
            case "14":
                return "3";

            default:
                return null;
        }
    }

    public static String openapiDomain(boolean test) {
        // 测试环境：https://test.wsmsd.cn/sit/api/v2/mms/openApi/wechatParamConf
        // 生产环境：https://s2.lakala.com/api/v2/mms/openApi/wechatParamConf
        if (test) {
            return "https://test.wsmsd.cn/sit";
        }
        else {
            return "https://s2.lakala.com";
        }
    }

    public static String approveUrl(boolean test) {
        // 测试环境地址 https://test.wsmsd.cn/sit/htk-api/customer/update/review
        // 生产环境地址 https://htkapi.lakala.com/api/customer/update/review
        if (test) {
            return "https://test.wsmsd.cn/sit/htk-api/customer/update/review";
        }
        else {
            return "https://htkapi.lakala.com/api/customer/update/review";
        }
    }

    public static String accessUrl(boolean test) {
        // 测试环境: https://test.wsmsd.cn/sit/htkregistration/merchant (POST)
        // ⽣产环境: https://htkactvi.lakala.com/registration/merchant (POST)
        if (test) {
            return "https://test.wsmsd.cn/sit/htkregistration/merchant";
        }
        else {
            return "https://htkactvi.lakala.com/registration/merchant";
        }
    }

    public static String accessQueryUrl(boolean test) {
        // 测试公网地址 https://test.wsmsd.cn/sit/htkmerchants
        // 生产地址 https://tkapi.lakala.com/htkmerchants
        if (test) {
            return "https://test.wsmsd.cn/sit/htkmerchants/open/merchant/info";
        }
        else {
            return "https://tkapi.lakala.com/htkmerchants/open/merchant/info";
        }
    }

    public static String accessTermQueryUrl(boolean test) {
        // 测试公网地址 https://test.wsmsd.cn/sit/htkmerchants
        // 生产地址 https://tkapi.lakala.com/htkmerchants
        if (test) {
            return "https://test.wsmsd.cn/sit/htkmerchants/open/merchant/microTermList";
        }
        else {
            return "https://tkapi.lakala.com/htkmerchants/open/merchant/microTermList";
        }
    }

    public static String subMerInfoQueryUrl(boolean test) {
        // 测试公网地址 https://test.wsmsd.cn/sit/htkmerchants
        // 生产地址 https://tkapi.lakala.com/htkmerchants
        // 接口地址 open/merchant/submer
        if (test) {
            return "https://test.wsmsd.cn/sit/htkmerchants/open/merchant/submer";
        }
        else {
            return "https://tkapi.lakala.com/htkmerchants/open/merchant/submer";
        }
    }

    public static String fileUrl(boolean test) {
        // 测试环境内网：http://htkactvi-sit.lakala.sh.in/registration/api/registration
        // 测试环境外网：https://test.wsmsd.cn/sit//htkregistration
        // 生产环境：https://htkactvi.lakala.com/registration
        // 1文件上传
        // 请求方式：post
        // 请求接口 /file/upload
        if (test) {
            return "https://test.wsmsd.cn/sit//htkregistration";
        }
        else {
            return "https://htkactvi.lakala.com/registration";
        }
    }

    public static String tokenUrl(boolean test) {
        // 测试公网地址 https://test.wsmsd.cn/sit/htkauth/oauth/token
        // ⽣产地址 https://tkapi.lakala.com/auth/oauth/token
        if (test) {
            return "https://test.wsmsd.cn/sit/htkauth";
        }
        else {
            return "https://tkapi.lakala.com/auth";
        }
    }

}
